import os

import click
from flask import Flask, request
from flask.cli import AppGroup
from flask_migrate import Migrate

from apps.tool import R
from config import config
# 加载环境变量文件，dotenv_path默认值为.env,override是表示是否可以重载，默认值为False
from db import db
from mtoken import TokenFactory, TOKEN_KEY, redis_client

env = os.getenv("ENV", "dev")
app = Flask(__name__)
app.config.from_object(config.get(env))
# db = SQLAlchemy(app)
db.init_app(app)
# 注册redis
redis_client.init_app(app)
# 执行数据库迁移相关操作。flask db指令不能直接使用，需要获取Migrate实例，这里注册Migrate实例
migrate = Migrate(app, db)

# 代码生成器命令注册---start
gen_cli = AppGroup('mole', help="自定义命令")


@gen_cli.command('gen', help="代码生成")
@click.option('-t', required=False, help="要代码生成的表")
@click.option('-m', type=click.Choice(['1', '2']), default="1", help="1->生成代码,2->查看元数据")
def create_gen(t, m):
    from generator import CodeGenerator
    CodeGenerator(db.engine).build(tableName=t, model=m)


app.cli.add_command(gen_cli)


# 代码生成器命令注册---end

def create_app():
    """
    初始化Flask实例
    :return:
    """
    from apps.sys.controller.user_controller import user
    app.register_blueprint(user, url_prefix="/sys/user")
    from apps.sys.controller.role_controller import role
    app.register_blueprint(role, url_prefix="/sys/role")
    from apps.sys.controller.callback_controller import callback
    app.register_blueprint(callback, url_prefix="/callback")
    return app


@app.before_request
def auth():
    """
    权限拦截器-全局处理
    :return:
    """
    token_strategy = TokenFactory.get_instance()
    token = request.headers.get(TOKEN_KEY, "")
    if request.path not in app.config['WHITE_LIST'] and token_strategy.get(token) is None:
        return R.fail("未登录", code=401)


@app.errorhandler(Exception)
def error(e):
    """
    全局异常处理
    :param e: 异常
    :return:
    """
    return R.fail(str(e), code=500)


@app.errorhandler(404)
def error(e):
    """
    404错误
    :param e:
    :return:
    """
    return R.fail("请求地址不存在", code=404)
